{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e662d8b8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "%pip install -qU fastapi-mcp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c0f32a59",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 最简单的 FastAPI + MCP 示例\n",
    "\n",
    "from fastapi import FastAPI\n",
    "from fastapi_mcp import FastApiMCP\n",
    "import nest_asyncio\n",
    "nest_asyncio.apply()\n",
    "\n",
    "# Your existing FastAPI app\n",
    "app = FastAPI()\n",
    "\n",
    "# Add MCP server to your FastAPI app\n",
    "mcp = FastApiMCP(\n",
    "    app,\n",
    "    name=\"My API MCP\",\n",
    "    describe_all_responses=True,     # 在工具描述中包含所有可能的响应模式\n",
    "    describe_full_response_schema=True  # 在工具描述中包含完整的 JSON 模式\n",
    ")\n",
    "\n",
    "# Mount the MCP server to your app\n",
    "mcp.mount()\n",
    "\n",
    "# Run your app as usual\n",
    "if __name__ == \"__main__\":\n",
    "    import uvicorn\n",
    "    uvicorn.run(app, host=\"0.0.0.0\", port=8000)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d31fd73",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 与原始 FastAPI 应用分开部署\n",
    "from fastapi import FastAPI\n",
    "from fastapi_mcp import FastApiMCP\n",
    "\n",
    "# 您的 API 应用\n",
    "api_app = FastAPI()\n",
    "# ... 在 api_app 上定义您的 API 端点 ...\n",
    "\n",
    "# 一个单独的 MCP 服务器应用\n",
    "mcp_app = FastAPI()\n",
    "\n",
    "# 从 API 应用创建 MCP 服务器\n",
    "mcp = FastApiMCP(api_app)\n",
    "\n",
    "# 将 MCP 服务器挂载到单独的应用\n",
    "mcp.mount(mcp_app)\n",
    "\n",
    "# 现在您可以分别运行两个应用：\n",
    "# uvicorn main:api_app --host api-host --port 8001\n",
    "# uvicorn main:mcp_app --host mcp-host --port 8000"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23321853",
   "metadata": {},
   "source": [
    "# 客户端配置\n",
    "\n",
    "```json\n",
    "{\n",
    "  \"mcpServers\": {\n",
    "    \"my-api-mcp\": {\n",
    "      \"url\": \"http://localhost:8000/mcp\",\n",
    "      \"alwaysAllow\": [],\n",
    "      \"disabled\": false\n",
    "    }\n",
    "  }\n",
    "}\n",
    "```\n",
    "\n",
    "\n",
    "```json\n",
    "{\n",
    "  \"mcpServers\": {\n",
    "    \"my-api-mcp-proxy\": {\n",
    "      \"command\": \"/Full/Path/To/Your/Executable/mcp-proxy\",\n",
    "      \"args\": [\"<http://127.0.0.1:8000/mcp>\"]\n",
    "    }\n",
    "  }\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b39178be",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Administrator\\AppData\\Local\\Temp\\ipykernel_9232\\1148449145.py:24: DeprecationWarning: `example` has been deprecated, please use `examples` instead\n",
      "  user_id: int = Path(..., description=\"用户的唯一数字标识符，必须是正整数\", example=123)\n",
      "C:\\Users\\Administrator\\AppData\\Local\\Temp\\ipykernel_9232\\1148449145.py:38: DeprecationWarning: mount() is deprecated and will be removed in a future version. Use mount_http() for HTTP transport (recommended) or mount_sse() for SSE transport instead.\n",
      "  mcp.mount()\n",
      "INFO:     Started server process [9232]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:57507 - \"GET /mcp HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:53295 - \"GET /mcp HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:53297 - \"POST /mcp/messages/?session_id=ab5babaa31ed445a940efdd847441da9 HTTP/1.1\" 202 Accepted\n",
      "INFO:     127.0.0.1:53298 - \"POST /mcp/messages/?session_id=ab5babaa31ed445a940efdd847441da9 HTTP/1.1\" 202 Accepted\n",
      "INFO:     127.0.0.1:53299 - \"POST /mcp/messages/?session_id=ab5babaa31ed445a940efdd847441da9 HTTP/1.1\" 202 Accepted\n",
      "INFO:     127.0.0.1:53300 - \"POST /mcp/messages/?session_id=ab5babaa31ed445a940efdd847441da9 HTTP/1.1\" 202 Accepted\n",
      "INFO:     127.0.0.1:53301 - \"POST /mcp/messages/?session_id=ab5babaa31ed445a940efdd847441da9 HTTP/1.1\" 202 Accepted\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "ERROR:    Exception in ASGI application\n",
      "Traceback (most recent call last):\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\uvicorn\\protocols\\http\\httptools_impl.py\", line 409, in run_asgi\n",
      "    result = await app(  # type: ignore[func-returns-value]\n",
      "             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\uvicorn\\middleware\\proxy_headers.py\", line 60, in __call__\n",
      "    return await self.app(scope, receive, send)\n",
      "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\fastapi\\applications.py\", line 1054, in __call__\n",
      "    await super().__call__(scope, receive, send)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\applications.py\", line 113, in __call__\n",
      "    await self.middleware_stack(scope, receive, send)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\middleware\\errors.py\", line 186, in __call__\n",
      "    raise exc\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\middleware\\errors.py\", line 164, in __call__\n",
      "    await self.app(scope, receive, _send)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\middleware\\exceptions.py\", line 63, in __call__\n",
      "    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\_exception_handler.py\", line 53, in wrapped_app\n",
      "    raise exc\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\_exception_handler.py\", line 42, in wrapped_app\n",
      "    await app(scope, receive, sender)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\routing.py\", line 716, in __call__\n",
      "    await self.middleware_stack(scope, receive, send)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\routing.py\", line 736, in app\n",
      "    await route.handle(scope, receive, send)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\routing.py\", line 290, in handle\n",
      "    await self.app(scope, receive, send)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\routing.py\", line 78, in app\n",
      "    await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\_exception_handler.py\", line 53, in wrapped_app\n",
      "    raise exc\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\_exception_handler.py\", line 42, in wrapped_app\n",
      "    await app(scope, receive, sender)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\routing.py\", line 76, in app\n",
      "    await response(scope, receive, send)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\responses.py\", line 158, in __call__\n",
      "    await send(\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\_exception_handler.py\", line 39, in sender\n",
      "    await send(message)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\_exception_handler.py\", line 39, in sender\n",
      "    await send(message)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\starlette\\middleware\\errors.py\", line 161, in _send\n",
      "    await send(message)\n",
      "  File \"d:\\software\\miniconda3\\envs\\MLOps\\Lib\\site-packages\\uvicorn\\protocols\\http\\httptools_impl.py\", line 517, in send\n",
      "    raise RuntimeError(msg % message_type)\n",
      "RuntimeError: Expected ASGI message 'http.response.body', but got 'http.response.start'.\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [9232]\n"
     ]
    }
   ],
   "source": [
    "# MCP 示例\n",
    "\n",
    "from fastapi import FastAPI, Path\n",
    "from fastapi_mcp import FastApiMCP\n",
    "import nest_asyncio\n",
    "nest_asyncio.apply()\n",
    "\n",
    "# Your existing FastAPI app\n",
    "app = FastAPI()\n",
    "\n",
    "# # (不推荐) 自动生成的 operation_id（类似于 \"read_user_users__user_id__get\"）\n",
    "# @app.get(\"/users/{user_id}\")\n",
    "# async def read_user(user_id: int):\n",
    "#     return {\"user_id\": user_id}\n",
    "\n",
    "# 显式 operation_id（工具将被命名为 \"get_user_info\"）\n",
    "@app.get(\n",
    "    \"/users/{user_id}\", \n",
    "    operation_id=\"get_user_info\",\n",
    "    summary=\"获取用户信息\",\n",
    "    description=\"根据用户ID获取用户的详细信息\",\n",
    "    response_description=\"包含用户基本信息的JSON对象\")\n",
    "async def read_user(\n",
    "    user_id: int = Path(..., description=\"用户的唯一数字标识符，必须是正整数\", example=123)\n",
    "):\n",
    "    return {\"user_id\": user_id}\n",
    "\n",
    "\n",
    "# Add MCP server to your FastAPI app\n",
    "mcp = FastApiMCP(\n",
    "    app,\n",
    "    name=\"My API MCP\",\n",
    "    describe_all_responses=True,     # 在工具描述中包含所有可能的响应模式\n",
    "    describe_full_response_schema=True,  # 在工具描述中包含完整的 JSON 模式\n",
    ")\n",
    "\n",
    "# Mount the MCP server to your app\n",
    "mcp.mount()\n",
    "\n",
    "# Run your app as usual\n",
    "if __name__ == \"__main__\":\n",
    "    import uvicorn\n",
    "    uvicorn.run(app, host=\"0.0.0.0\", port=8000)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MLOps",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
